package com.zmt.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zmt.content.dto.BindTeachplanMediaDto;
import com.zmt.content.dto.SaveTeachPlanDto;
import com.zmt.content.dto.TeachplanDto;
import com.zmt.content.mapper.TeachplanMapper;
import com.zmt.content.mapper.TeachplanMediaMapper;
import com.zmt.content.po.Teachplan;
import com.zmt.content.po.TeachplanMedia;
import com.zmt.content.service.TeachPlanService;
import com.zmt.xuechengplusbase.exception.xuechengplusException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.zmt.xuechengplusbase.exception.CommonError.QUERY_NULL;

@Slf4j
@Service
public class TeachPlanServiceImpl implements TeachPlanService {
    @Autowired
    private TeachplanMapper teachplanMapper;

    @Autowired
    private TeachplanMediaMapper teachplanMediaMapper;

    /**
     * 根据课程id查询课程计划
     * @param courseId
     * @return
     */
    @Override
    public List<TeachplanDto> selectTreeNodes(Long courseId) {
        if (courseId == null) {
            return null;
        }
        return teachplanMapper.selectTreeNodes(courseId);
    }

    /**
     * 新增或修改课程计划
     * 根据是否存在id来判断是进行新增还是修改（如果不是页面上传过来的参数的话，这样安全吗）
     * <!--安全，传过来的并没有表中id的数据，传过来的是课程id-->
     * @param teachPlanDto
     */
    @Override
    public String saveTeachPlan(SaveTeachPlanDto teachPlanDto) {
        Long id = teachPlanDto.getId();
        Teachplan teachplan = new Teachplan();
        BeanUtils.copyProperties(teachPlanDto, teachplan);
        if (id == null) {
            //说明进行新增操作
            Long parentid = teachplan.getParentid();
            Long courseId = teachplan.getCourseId();
            //新增时要进行一个排序，具体实现思想为根据不同课程的添加时是父结点的第几位子节点
            //select count(1) from teachplan where courseId=#{courseId} and parentId=#{parentId}
            LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(parentid != null, Teachplan::getParentid, parentid)
                    .eq(courseId != null, Teachplan::getCourseId, courseId);
            Integer count = teachplanMapper.selectCount(wrapper);
            // 如果采取count子节点数量的话，如果删除一个节点后再去添加不就有了相同的orderby了吗？(已解决)
            teachplan.setOrderby(count + 1);
            int insert = teachplanMapper.insert(teachplan);
            if (insert <= 0) {
                xuechengplusException.cast("新增课程计划失败");
            }
        } else {
            //传参中有id因此是已经保存在数据库中的数据，因此进行修改操作
            int i = teachplanMapper.updateById(teachplan);
            if (i <= 0) {
                xuechengplusException.cast("更改课程计划失败");
            }
        }
        return "操作成功";
    }

    /**
     * 删除模块
     * 如何解决删除章节问题orderBy排序呢？
     * 1、将删除字段后的所有字段orderBy-1
     * 2、换一种排序方式，让其无法影响比如时间戳
     * @param teachPlanId
     * @return
     */
    @Override
    @Transactional
    public String deleteTeachPlan(Long teachPlanId) {
        /*
        进行一下分析，首先需要删除teachPlan表中章节数据，其次需要去删除媒资表中视频数据
         */
        //先判断是大章节还是小章节，如果是大章节去判断有无子节点，如果是小章节查询关联媒资表
        Teachplan teachplan = teachplanMapper.selectById(teachPlanId);
        if (teachplan == null) {
            xuechengplusException.cast(QUERY_NULL);
        }
        Integer orderby = teachplan.getOrderby();
        Long courseId = teachplan.getCourseId();
        Integer grade = teachplan.getGrade();
        if (grade == 1) {
            //删除大章节
            //先查询还有没有子节点
            LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Teachplan::getParentid, teachPlanId);
            Integer count = teachplanMapper.selectCount(wrapper);
            if (count > 0) {
                xuechengplusException.cast("大章节中还存在小章节，删除失败");
            }
            int i = teachplanMapper.deleteById(teachPlanId);
            if (i > 0) {
                //删除成功的话进行一次排序字段修改
                //开始修改
                //sql: update teachplan set order_by=order_id-1 where order_id >=#{orderBy} and course_id =#{} and grade=#{}
                if (count!=orderby)
                teachplanMapper.updateOrderBy(orderby,courseId,grade);
                return "删除成功";
            }else {
                xuechengplusException.cast("删除大章节失败");
            }
        } else {
            //删除小章节
            //先获取关联的媒资信息
            TeachplanMedia teachplanMedia = teachplanMediaMapper.selectByTeachPlanId(teachPlanId);
            if (teachplanMedia != null) {
                int i = teachplanMediaMapper.deleteById(teachplanMedia);
                if (i <= 0) {
                    xuechengplusException.cast("删除媒资信息失败");
                }
            }
            // delete from teachplan where id = #{id} and parentId != 0
            int j = teachplanMapper.deleteXZJ(teachPlanId);
            if (j <= 0) {
                xuechengplusException.cast("删除小节失败");
            }
            teachplanMapper.updateOrderBy(orderby,courseId,grade);
        }
        return "操作成功";
    }

    /**
     * 上移或下移
     *
     * @param type
     * @param teachPlanId
     */
    @Override
    public void moveOrder(String type, Long teachPlanId) {
        //实现思路：根据前端传过来的type判断上移还是下移，然后判断Grade只移动同类型的所谓移动，无非就是OrderBy字段互换
        /**
         * equals对比字段有点硬编码的意思，或许可以把moveup与movedown提取出来成为一个常量
         */
        if (type.equals("moveup")) {
            //上移操作
            Teachplan teachplan = teachplanMapper.selectById(teachPlanId);
            Integer nextOrder = teachplan.getOrderby();
            if (nextOrder == 1) {
                //说明在最上面了
                xuechengplusException.cast("已经在最前面了，宝");
            }
            Long parentid = teachplan.getParentid();
            Long courseId = teachplan.getCourseId();

            Integer perOrder = nextOrder - 1;
            //接着去找orderBy为nextOrder上一个那个课程的id
            //实现方式：1、自己定义一个sql语句 select * from teachplan where parentId=#{parentId} and orderBy = #{perOrder}
            //select * from teachplan where course_id=#{courseId} and parentId=#{parentId} and orderBy = #{perOrder}
            //2、直接set update teachplan set order_by = order_by-1 where id = #{id}
            //          查出来要交换位置的teachPlanId
            //          update teachplan set order_by =order_by+1 where id =
            LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
            //em这样似乎不能进行大章节互换，对比parentId只能说明小章节可以正常更改,大章节需要知道课程id
            wrapper.eq(Teachplan::getParentid, parentid)
                    .eq(Teachplan::getOrderby, perOrder)
                    .eq(Teachplan::getCourseId,courseId);
            Teachplan perTeachPlan = teachplanMapper.selectOne(wrapper);
            perTeachPlan.setOrderby(nextOrder);
            teachplan.setOrderby(perOrder);
            teachplanMapper.updateById(teachplan);
            teachplanMapper.updateById(perTeachPlan);
        }
        if (type.equals("movedown")){
            //下移操作
            Teachplan teachplan = teachplanMapper.selectById(teachPlanId);
            Long parentid = teachplan.getParentid();
            Long courseId = teachplan.getCourseId();
            LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Teachplan::getParentid, parentid)
                    .eq(Teachplan::getCourseId,courseId);
            Integer count = teachplanMapper.selectCount(wrapper);
            Integer perOrder = teachplan.getOrderby();
            if (perOrder == count) {
                //说明在最下面了
                xuechengplusException.cast("已经在最下面了，宝");
            }
            //接下来互换orderBy字段
            Integer nextOrder = perOrder+1;
            teachplan.setOrderby(nextOrder);
            wrapper.eq(Teachplan::getOrderby, nextOrder);
            Teachplan next = teachplanMapper.selectOne(wrapper);
            next.setOrderby(perOrder);
            teachplanMapper.updateById(teachplan);
            teachplanMapper.updateById(next);
        }
    }

    /**
     * 绑定媒资和教学计划
     * @param bindTeachplanMediaDto
     */
    @Override
    @Transactional
    public void associationMedia(BindTeachplanMediaDto bindTeachplanMediaDto) {
        Long teachplanId = bindTeachplanMediaDto.getTeachplanId();
        Teachplan teachplan = teachplanMapper.selectById(teachplanId);
        if (teachplan==null){
            xuechengplusException.cast("教学计划不存在");
        }
        Long courseId = teachplan.getCourseId();
        //先对课程计划进行查询，看是否以及存在绑定关系(不查也无所谓)
        //如果存在，进行删除操作
        teachplanMediaMapper.delete(new LambdaQueryWrapper<TeachplanMedia>().eq(TeachplanMedia::getTeachplanId,bindTeachplanMediaDto.getTeachplanId()));
        //进行绑定
        TeachplanMedia teachplanMedia = new TeachplanMedia();
        BeanUtils.copyProperties(bindTeachplanMediaDto,teachplanMedia);
        teachplanMedia.setCourseId(courseId);
        teachplanMedia.setMediaFilename(bindTeachplanMediaDto.getFileName());
        teachplanMediaMapper.insert(teachplanMedia);
    }

    /**
     * 用于学习中心远程调用查询是否具有试学
     * @param teachplanid
     * @return
     */
    @Override
    public String getTeachPlanIsPreview(Long teachplanid) {
        Teachplan teachplan = teachplanMapper.selectById(teachplanid);
        String isPreview = teachplan.getIsPreview();
        return isPreview;
    }
}